/*******************************************************************************
 * Copyright 2011 @ Kapil Viren Ahuja
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.kapilvirenahuja.eamsteps.dataloader.impl;

import java.lang.reflect.Method;

import org.apache.commons.lang.StringUtils;

import com.kapil.framework.exception.impl.DataProviderException;
import com.kapil.framework.lang.ReflectionUtil;
import com.kapilvirenahuja.eamsteps.dataloader.AbstractDataLoader;
import com.kapilvirenahuja.eamsteps.dataloader.IDataLoader;
import com.kapilvirenahuja.eamsteps.form.IDataForm;
import com.kapilvirenahuja.eamsteps.info.HeaderInfo;

/**
 * This implementation of {@link IDataLoader} provides capabilities to read values that have already been 
 * created and stored in the {@link IDataForm}. This class will not create any new objects. This class
 * will check for the datatype to be <code>reference</code> to proceed.
 * 
 * 
 */
public class ReferenceDataLoader extends AbstractDataLoader implements IDataLoader
{

    public ReferenceDataLoader()
    {
        super.next = null;
    }


    public ReferenceDataLoader(IDataLoader dataLoader)
    {
        super.next = dataLoader;
    }


    /**
     * @see AbstractDataLoader#setup(String, String, HeaderInfo, Object, IDataForm)
     * 
     */
    @Override
    protected void doSetup(String dataTableName, String rowId, String data, HeaderInfo header, Object objectInstance, final IDataForm form)
    {
        if (StringUtils.equalsIgnoreCase(header.getType(), "reference"))
        {
            Object value = loadReference(data, form);

            if (value == null)
            {
                throw new DataProviderException("There is a missing reference. Please check [" + data + "] on the form.");
            }

            Method setter = ReflectionUtil.findAdder(objectInstance.getClass(), header.getPropertyName());
            if (setter == null)
            {
                throw new DataProviderException("Unable to locate setter for [" + header.getPropertyName() + "]");
            }

            try
            {
                setter.invoke(objectInstance, value);
            }
            catch (Exception ex)
            {
                throw new DataProviderException("Unable to invoke the setter for [" + objectInstance.getClass() + "] on row [" + rowId + "]", ex);
            }

        }
    }


    private Object loadReference(String data, IDataForm form)
    {
        if (StringUtils.equalsIgnoreCase(data, "null"))
        {
            return null;
        }

        // Format for reference objects is: "ObjectName [row number]"
        String referenceObject = StringUtils.substringBefore(data, " [");
        Integer rowNumber = Integer.parseInt(StringUtils.substringBetween(data, "[", "]"));


        return form.getData(referenceObject, rowNumber);
    }

}
